package optimizacion;


public class Cromosoma {

	public Gen gen;
    
    protected int longitud;
    
    public double aptitud;
    protected double aptitudRev;
    protected double aptitudEscaladoLineal;    
    protected double puntuacion;
    protected double puntuacionAcumulada;
    
    public Cromosoma(int longitud){
    	this.longitud = longitud;
    	this.gen = new Gen(longitud);
    }
    
    public Cromosoma(){
    
    } 

    /**
     * Inicializa el gen generando su genotipo con valores random
     */
	public void inicializar(int valorSemilla, boolean semilla){
		gen.inicializar(valorSemilla, semilla);
	}
//	
//	/**
//	 * Calcula el fenotipo de un iesimo gen
//	 * @param d
//	 * @param f
//	 * @return
//	 */
//	public double calcularFenotipoIesimo(double [][] d, double [][] f){
//		return gen.calcularFenotipo(d, f);
//	}
	
	
	 public double calcularAptitud(double [][] d, double [][] f) {   
	    	aptitud = gen.calcularFenotipo(d, f);
	    	aptitudRev = aptitud;
	    	aptitudEscaladoLineal = aptitud;
	    	return aptitud;
	    }
   
	    
    public double revisarAptitud(double cmax) {   
    	aptitudRev =  calcularAptitudRevisadaMinimizacion(cmax);
    	aptitudEscaladoLineal = aptitudRev;
    	return aptitudRev;
    }
	
    public double calcularAptitudRevisadaMinimizacion(double cmax) {
		aptitudRev =  Math.abs(cmax*1.05) - aptitud; // he puesto abs porque si son todos negativos, uno se quedaria negativo
    	return aptitudRev;
	}
    
	/**
	 * Calcula la aptitud con escalado lineal
	 * @param P
	 * @param media
	 * @param cmax
	 * @param cmin
	 * @return
	 */
	public double calcularAptitudEscaladoLineal(double P, double media, double cmax, double cmin) {   
		double a = ((P - 1) * media) / (cmax - media);
		
		if (a < 0) // // para evitar negativos y que de valores erroneos
			a = media / (media - cmin);
			
		a = a + 0.05; // para evitar 0 y que de valores erroneos
		
		double b = (1 - a) * media; 		
		
    	aptitudEscaladoLineal =  a * aptitudRev + b;
    	
    	//System.out.println("----- m: " + media + ", a:" + a + ", b: " + b+ ",a:" + aptitud +", aR: "  + aptitudRev + ", aEL: " + aptitudEscaladoLineal);
    	
    	return aptitudEscaladoLineal;
    } 

	
	/**
	 * Calcula la puntuacion de un cromosoma
	 * @param total
	 * @return
	 */
	public double calcularPuntuacion(double total){
		puntuacion = aptitudEscaladoLineal / total;
		return puntuacion;
	}
	
//	public double calcularPuntuacion(double peorAptitud, double total){
//		puntuacion = ((peorAptitud - aptitudEscaladoLineal) + 0.01) / total;
//		return puntuacion;
//	}
	
	/**
	 * Calcula la puntuacion acumulada de un cromosoma
	 * @param acumulado
	 * @return
	 */
	public double calcularPuntuacionAcumulada(double acumulado){
		puntuacionAcumulada = puntuacion + acumulado;
		return puntuacionAcumulada;
	}  
	
	public Cromosoma clone (){
    	Cromosoma crom = new Cromosoma(); 	

    	crom.longitud = longitud;
    	crom.aptitud = aptitud;
    	crom.aptitudRev = aptitudRev;
    	crom.aptitudEscaladoLineal = aptitudEscaladoLineal;
    	crom.puntuacion = puntuacion;
    	crom.puntuacionAcumulada = puntuacionAcumulada;
    	crom.gen = gen.clone();  	
    	
    	return crom;
    }
}
